package com.future.interceptor;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import java.lang.reflect.Method;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * 方法拦截器拦截进行AOP动态类的增强
 * spring aop：基于动态代理的面向切面编程  aspect oriented programming
 * spring ioc：控制反转 把对象的创建以及依赖关系交给spring容器管理  inversion of control
 * MethodInterceptor：基于cglib动态代理
 * jdk动态代理：基于接口  实现invocationHandler
 * cglib：基于类  实现MethodInterceptor
 */
public class AsyncAopAdvice implements MethodInterceptor {

    private static final ExecutorService executor = Executors.newFixedThreadPool(3); //线程池可以动态配置通过传参传入，这里为了方便直接写死

    public AsyncAopAdvice() {

    }

    @Override
    public Object invoke(MethodInvocation invocation) {
        Method method = invocation.getMethod();
        Callable<Object> task = () -> {
            try {
                Object result = invocation.proceed();
                if (result instanceof Future) {
                    return ((Future) result).get();
                }
                return result;
            } catch (Throwable var4) {
                var4.printStackTrace();
            }
            return null;
        };
        return execute(task, method.getReturnType());
    }

    private Object execute(Callable<Object> task, Class<?> returnType) {
        if (CompletableFuture.class.isAssignableFrom(returnType)) {
            return CompletableFuture.supplyAsync(() -> {
                try {
                    return task.call();
                } catch (Throwable var2) {
                    throw new CompletionException(var2);
                }
            }, executor);
        } else if (Future.class.isAssignableFrom(returnType)) {
            return executor.submit(task);
        } else {
            executor.submit(task);
            return null;
        }
    }


}
